package com.practice.gmall.realtime.util;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.flink.shaded.guava18.com.google.common.base.CaseFormat;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

@Slf4j
public class JdbcUtil {

    public static Connection getJdbcConn(String driver, String url, String user, String pwd) {

        try {
            Class.forName(driver);
            return DriverManager.getConnection(url, user, pwd);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException("Driver clas not found : " + driver);
        } catch (SQLException e) {
            //throw new SQLException("failed to get connection, url: " + url);
            //e.printStackTrace();// 作用是什么? 将错误信息打印到控制台，其中的打印的字符会占用堆内存空间
            log.error("failed to get connection, url: " + url, e.getMessage());
        }
        return null;

        /*
        // todo 为什么这种写法有问题??, 提示连接到phoenix错误
        try {
            Class.forName(driver);

        } catch (ClassNotFoundException e) {
                        throw new RuntimeException(e);
            //throw new RuntimeException("Driver clas not found : " + driver);
        }

        try {
            return DriverManager.getConnection(url, user, pwd);
        } catch (SQLException e) {
            throw new RuntimeException(e);
            //throw new RuntimeException("failed to get connection, url: " + url);
        }*/
    }

    /**
     * @param conn
     * @param querySql
     * @param args
     * @param tClass
     * @param isUnderLineToCamel
     * @Description: 将查询到的结果集逐行封装成指定的类型T
     * todo 好好复习这个方法的编写
     * @return: java.util.List<T>
     * @Author: lzy
     * @Date:2023-02-16 - 22:15
     */
    public static <T> List<T> queryList(Connection conn, String querySql, Object[] args, Class<T> tClass, boolean... isUnderLineToCamel) throws Exception {
        boolean flag = false;
        if (isUnderLineToCamel.length == 1) {
            flag = isUnderLineToCamel[0];
        }

        ArrayList<T> list = new ArrayList<>();
        PreparedStatement ps = conn.prepareStatement(querySql);
        // 给占位符赋值
        for (int i = 0; args != null && i < args.length; i++) {
            Object arg = args[i];
            ps.setObject(i + 1, arg);
        }
        // id  name  age
        // 1   zs   10
        // 2   lisi  10
        ResultSet resultSet = ps.executeQuery();
        ResultSetMetaData metaData = resultSet.getMetaData(); // 表结构: 列名, 列的类型, 多少列 ...

        while (resultSet.next()) {  // 遍历所有行
            T t = tClass.newInstance();  // 利用无参构造器创建对象
            list.add(t);
            // 遍历所有的列
            for (int i = 1; i <= metaData.getColumnCount(); i++) {
                // 获取列名: 列名要和T类型的属性名保持一致
                String name = metaData.getColumnName(i);
                if (flag) {
                    // 下划线转成驼峰  a_a =>aA aa_b =>aaB
                    name = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, name);
                }

                Object v = resultSet.getObject(i);
                BeanUtils.setProperty(t, name, v); // 给对象的属性赋值: t.name=v
            }
        }

        return list;
    }

    public static void closeConnection(Connection conn) throws SQLException {
        if (conn != null) {
            conn.close();
        }
    }
}
